home *** CD-ROM | disk | FTP | other *** search
- /* PPC.C - Pretty Printer for C
- Created from CB on SIMTEL20 by Richard Conn
- CB was heavily modified to create PPC */
-
- #include <stdio.h>
-
- #define TITLE "Pretty Printer for C, Beta Test Version 1.0"
- #define MAXBRAC 20 /* maximum number of open braces allowed */
- #define IFLEVEL 20 /* maximum number of nested IFs allowed */
-
- int slevel[IFLEVEL];
- int spflg[MAXBRAC][IFLEVEL];
- int sind [MAXBRAC][IFLEVEL];
- int siflev[IFLEVEL];
- int sifflg[IFLEVEL];
- int clevel = 0; /* Number of open braces */
- int iflev = 0; /* Number of active IFs */
- int ifflg = -1; /* Indicates if we have an active IF */
- int level = 0;
- int ind[IFLEVEL]; /* Indentation amount for a particular IF */
- int pflg[IFLEVEL]; /* Number of characters to indent for a particular IF */
- int eflg = 0; /* We are in an ELSE? */
- int paren = 0; /* Number of open parentheses */
- int tabcount = 4; /* Number of characters to indent */
- char lchar;
- char pchar;
- int aflg = 0;
- int stabs[MAXBRAC][IFLEVEL];
- int qflg = 0;
-
- /* The following are reserved words used for special processing */
- char *wstr[] = {
- "typedef",
- "struct",
- "union",
- "int",
- "char",
- "unsigned",
- "long",
- "auto",
- NULL
- };
- char *wrsvwds[] = {
- "int",
- "char",
- "unsigned",
- "long",
- "auto",
- NULL
- };
- char *wif[] = {
- "if",
- NULL
- };
- char *welse[] = {
- "else",
- NULL
- };
- char *wfor[] = {
- "for",
- NULL
- };
- char *wds[] = {
- "case",
- "default",
- NULL
- };
-
- /* J is the index for the next character in the STRING buffer
- STRING is the buffer in which the output line is built */
- int j = 0;
- char string[400];
-
- char cc;
- int sflg = 1;
- int bflg = 0;
- int peek = -1;
- int tabs = 0;
- int lastchar = ' ';
- int cin;
-
- /* Input and output buffers */
- FILE *inpbuf;
- FILE *outbuf;
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- char bakfil[100]; /* name of current backup file */
- int filno; /* number of current file */
- int cont; /* local continuation flag */
- int ct; /* count of local open parens */
- int eflg; /* indicates we are in an ELSE */
- int i;
-
- if (argc == 1) {
- printf ("%s\n", TITLE);
- printf (" Syntax: ppc [-i#] filename.ext [filename.ext ...]\n");
- printf (" Options:\n");
- printf (" -i# Set indentation level for files\n");
- exit (0);
- }
-
- /* Zero indentation indicator and indent character count buffers */
- for (i=0; i<IFLEVEL; i++) {
- ind[i] = 0;
- pflg[i] = 0;
- }
-
- /* Main Loop */
- for (filno=1; argv[filno]!=NULL; filno++) {
-
- /* Process next file (if not an option) */
- if (*argv[filno] != '-') {
- mkext (bakfil, argv[filno], "bak");
- unlink (bakfil);
- rename (argv[filno], bakfil);
- if ((inpbuf = fopen (bakfil, "r")) == NULL) {
- perror (bakfil);
- exit (1);
- }
- if ((outbuf = fopen (argv[filno], "w")) == NULL) {
- perror (argv[filno]);
- exit (1);
- }
- fprintf (stderr, " Pretty Printing %s\n", argv[filno]);
- while ( (cin = getchr()) != EOF) {
- switch(cin) {
- case ' ':
- case '\t':
- if (lookup(welse) == 1) {
- gotelse ();
- if (sflg == 0 || j > 0) string[j++] =cin;
- putz ();
- sflg = 0;
- break;
- }
- if (sflg == 0 || j > 0) string[j++] =cin;
- break;
- case '\n':
- if ((eflg = lookup(welse)) == 1) gotelse();
- putz();
- fprintf (outbuf,"\n");
- sflg = 1;
- if (eflg == 1) {
- pflg[level]++;
- tabs++;
- }
- else
- if (pchar == lchar)
- aflg = 1;
- break;
- case '{':
- if (lookup(welse) == 1) gotelse();
- siflev[clevel]= iflev;
- sifflg[clevel]= ifflg;
- iflev = ifflg = 0;
- clevel++;
- if (sflg == 1 && pflg[level] != 0) {
- pflg[level]--;
- tabs--;
- }
- string[j++] =cin;
- putz ();
- getnl ();
- putz ();
- fprintf (outbuf,"\n");
- tabs++;
- sflg = 1;
- if (pflg[level] > 0) {
- ind[level] = 1;
- level++;
- slevel[level] = clevel;
- }
- break;
- case '}':
- clevel--;
- if ((iflev = siflev[clevel]-1) < 0) iflev = 0;
- ifflg = sifflg[clevel];
- putz ();
- tabs--;
- ptabs ();
- if ((peek = getchr()) == ';') {
- fprintf (outbuf, "%c;", cin);
- peek = -1;
- }
- else fprintf (outbuf,"%c", cin);
- getnl ();
- putz ();
- fprintf (outbuf,"\n");
- sflg = 1;
- if (clevel < slevel[level]) if (level > 0) level--;
- if (ind[level] != 0) {
- tabs -= pflg[level];
- pflg[level] =0;
- ind[level] = 0;
- }
- break;
- case '"':
- case '\'':
- string[j++] =cin;
- while ((cc = getc(inpbuf)) !=cin) {
- string[j++] =cc;
- if (cc == '\\') string[j++] = getc(inpbuf);
- if (cc == '\n') {
- putz();
- sflg = 1;
- }
- }
- string[j++] =cc;
- if (getnl() ==1) {
- lchar = cc;
- peek = '\n';
- }
- break;
- case ';':
- string[j++] =cin;
- putz ();
- if (pflg[level] > 0 && ind[level] == 0) {
- tabs -= pflg[level];
- pflg[level] = 0;
- }
- getnl ();
- putz ();
- fprintf (outbuf,"\n");
- sflg = 1;
- if (iflev > 0)
- if (ifflg == 1) {
- iflev--;
- ifflg = 0;
- }
- else iflev = 0;
- break;
- case '\\':
- string[j++] =cin;
- string[j++] =getchr();
- break;
- case '?':
- qflg = 1;
- string[j++] =cin;
- break;
- case ':':
- string[j++] =cin;
- if (qflg == 1) {
- qflg = 0;
- break;
- }
- if (lookup(wrsvwds) == 1) break;
- if (lookup(wds)== 0) {
- sflg = 0;
- putz ();
- }
- else {
- tabs--;
- putz ();
- tabs++;
- }
- if ((peek = getchr()) == ';') {
- fprintf (outbuf, ";");
- peek = -1;
- }
- getnl ();
- putz ();
- fprintf (outbuf,"\n");
- sflg = 1;
- break;
- case '/':
- string[j++] =cin;
- if ((peek = getchr()) != '*') break;
- string[j++] = peek;
- peek = -1;
- comment ();
- break;
- case ')':
- paren--;
- string[j++] = cin;
- putz ();
- if (getnl() == 1) {
- peek = '\n';
- if (paren != 0) aflg = 1;
- else if (tabs > 0) {
- pflg[level]++;
- tabs++;
- ind[level] = 0;
- }
- }
- break;
- case '#':
- string[j++] =cin;
- while ((cc = getc(inpbuf)) != '\n') string[j++] = cc;
- string[j++] =cc;
- sflg = 0;
- putz ();
- sflg = 1;
- break;
- case '(':
- string[j++] =cin;
- paren++;
- if (lookup(wfor) == 1) {
- while ((cin = xgets()) != ';');
- ct = 0;
- cont = 1;
- while (cont) {
- while ((cin = xgets()) != ')') {
- if (cin== '(') ct++;
- }
- if(ct != 0) {
- ct--;
- }
- else cont = 0;
- }
- paren--;
- putz ();
- if (getnl() ==1) {
- peek = '\n';
- pflg[level]++;
- tabs++;
- ind[level] = 0;
- }
- break;
- }
- if (lookup(wif)== 1) {
- putz ();
- stabs[clevel][iflev] = tabs;
- spflg[clevel][iflev] = pflg[level];
- sind[clevel][iflev] = ind[level];
- iflev++;
- ifflg = 1;
- }
- break;
- default:
- string[j++] = cin;
- if (cin != ',') lchar = cin;
- break;
- }
- }
- fclose (inpbuf);
- fclose (outbuf);
- }
- /* Process an option */
- else {
- option (&argv[filno][1]);
- }
- }
- }
-
- /* Process an option on the command line */
- option (item)
- char *item;
- {
- switch (*item) {
- case 'i' :
- case 'I' :
- tabcount = atoi (++item);
- break;
- default :
- fprintf (stderr, "Invalid option in command line: %s\n", item);
- break;
- }
- }
-
- /* Output leading indentation characters on the line */
- ptabs()
- {
- int i, k;
-
- for (i = 0; i < tabs; i++) {
- for (k = 0; k<tabcount; k++)
- fprintf (outbuf, " ");
- }
- }
-
- /* Return the next non-space or non-tab character and set PEEK to -1
- and PCHAR to LASTCHAR as side effects */
- getchr()
- {
- if (peek < 0 && lastchar != ' ' && lastchar != '\t') pchar = lastchar;
- if (peek == '\t') peek = ' ';
- if (peek == ' ' && peek == lastchar) {
- peek = -1;
- }
- while (peek < 0) {
- peek = getc (inpbuf);
- if (peek == EOF) break;
- if (peek == '\t') peek = ' ';
- if (peek == ' ' && peek == lastchar) peek = -1;
- }
- lastchar = peek;
- peek = -1;
- return (lastchar);
- }
-
- /* If the STRING buffer is not empty (J>0), output indentation tabs
- and the STRING buffer after appending a null to the STRING buffer
- and reset the STRING buffer to empty */
- putz()
- {
- int k;
-
- if (j > 0) {
- if (sflg != 0) {
- ptabs();
- sflg = 0;
- if (aflg == 1) {
- aflg = 0;
- if (tabs > 0) {
- for (k = 0; k<tabcount; k++) fprintf (outbuf, " ");
- }
- }
- }
- string[j] = '\0';
- fprintf (outbuf, "%s", string);
- j = 0;
- }
- else {
- if (sflg != 0) {
- sflg = 0;
- aflg = 0;
- }
- }
- }
-
- /* Return 1 if the first non-blank token in STRING is an element of
- the passed table */
- lookup(tab)
- char *tab[];
- {
- char r;
- int l, kk, k, i;
-
- if (j < 1) return(0);
- kk = 0;
- while (string[kk] == ' ') kk++;
- for (i = 0; tab[i] != NULL; i++) {
- l = 0;
- for (k = kk; (r= tab[i][l++]) == string[k] && r !='\0'; k++);
- if (r == '\0' && (string[k] < 'a' || string[k] > 'z')) return(1);
- }
- return(0);
- }
-
- /* Return next character which is not an escaped character (leading
- back slash), a character constant, a string constant, or a new
- line (building the STRING buffer as we encounter these other items) */
- xgets()
- {
- int ch;
-
- while (1) {
- if ((ch = string[j++]= getchr()) == '\\') {
- string[j++] = getchr();
- }
- else {
- if (ch == '\'' || ch == '"') {
- while ((cc = string[j++] = getchr()) != ch) {
- if (cc == '\\') string[j++] = getchr();
- }
- }
- else {
- if (ch == '\n') {
- putz ();
- aflg = 1;
- }
- else return(ch);
- }
- }
- }
- }
-
- /* We got an ELSE clause, so process if levels et al */
- gotelse()
- {
- tabs = stabs[clevel][iflev];
- pflg[level] = spflg[clevel][iflev];
- ind[level] = sind[clevel][iflev];
- ifflg = 1;
- }
-
- /* Skip to next non-space, non-tab, or non-comment character, returning
- 1 if that character is a new line and 0 otherwise */
- getnl()
- {
- while ((peek = getchr()) == '\t' || peek == ' ') {
- string[j++] = peek;
- peek = -1;
- }
- if ((peek = getchr()) == '/') {
- peek = -1;
- if ((peek = getchr()) == '*') {
- string[j++] ='/';
- string[j++] ='*';
- peek = -1;
- comment();
- }
- else string[j++] = '/';
- }
- if ((peek = getchr()) == '\n') {
- peek = -1;
- return (1);
- }
- return (0);
- }
-
- /* Process comment, copying it into the output STRING buffer and allowing
- for nested comments */
- comment()
- {
- int repeat;
- int gotstar;
-
- repeat = 1;
- while (repeat) {
- while ((cin = string[j++] = getc(inpbuf)) != '*') {
- if (cin== '\n') {
- putz();
- sflg = 1;
- }
- }
-
- /* We got an asterisk */
- if (string[j-2]=='/') {
- fprintf (stderr, "Input has nested comments\n");
- comment ();
- }
- else {
- gotstar = 1;
- while (gotstar)
- if ((cin = string[j++] = getc(inpbuf)) != '*') gotstar = 0;
- if (cin == '/') repeat = 0;
- if (cin == '\n') {
- putz ();
- sflg = 1;
- }
- }
- }
- }
-
- /* Build a new file name string (NEW) given the first part of an old
- file name string (OLD) and an extension (EXT) to be placed at the end of
- the new file name string */
- mkext(new, old, ext)
- char *new;
- char *old;
- char *ext;
- {
- /* copy file name */
- while ((*old!='\0')&&(*old!='.')) *new++ = *old++;
-
- /* add a dot for the extension */
- *new++ = '.';
-
- /* copy extension */
- while (*ext!='\0') *new++ = *ext++;
-
- /* add string terminator */
- *new = '\0';
- }
-